package org.example.events.hostable.sales;
import org.example.models.abstracts.AbstractEvent;
import org.example.models.abstracts.AbstractItem;
import org.example.models.interfaces.own.Ownable;
import org.example.person.Person;

import java.util.*;


public class SalesEvent extends AbstractEvent implements Ownable {

    protected record Client(Person person, Map<Class<? extends AbstractItem>, Integer> request) {}
    private enum Message {
        IN_QUEUE("стоять в очереди"),
        ENTERED("зайти в магазин"),
        LEFT("уйти из магазина"),
        TRADING("покупать товары"),
        TRADED("купить товары");
        private final String message;
        Message(String message) { this.message = message; }

        @Override
        public String toString() {
            return message;
        }
    }
    private Map<Class<? extends AbstractItem>, List<AbstractItem>> stock;

    private Map<Class<? extends AbstractItem>, Integer> prices;

    private final Queue<Client> clients;

    public SalesEvent() {
        super("Sales");
        stock = new HashMap<>();
        clients = new LinkedList<>();
    }

    protected boolean processClient(BuyAction buyAction) {
        Client client = clients.poll();
        if (client == null) return false;

        Person person = client.person();
        Map<Class<? extends AbstractItem>, Integer> request = client.request();

        removeObserver(person);
        observers.forEach(observer -> notifyObserver(observer, Message.IN_QUEUE));
        notifyObserver(person, Message.TRADING);


        request.forEach((itemCls, count) -> {
            int price = prices.get(itemCls);
            for(int i = 0; i < count; i++) {
                person.act(buyAction.amount(price).item(stock.get(itemCls).get(0)));
            }
        });

        notifyObserver(person, Message.TRADED);
        notifyObserver(person, Message.LEFT);

        return true;
    }

    protected void setStock(Map<Class<? extends AbstractItem>, List<AbstractItem>> stock) {
        this.stock = stock;
    }


    public Map<Class<? extends AbstractItem>, List<AbstractItem>> getStock() {
        return stock;
    }

    public Map<Class<? extends AbstractItem>, Integer> getPrices() {
        return prices;
    }

    protected void setPrices(Map<Class<? extends AbstractItem>, Integer> prices) {
        this.prices = prices;
    }

    protected void addClient(Client client) {
        addObserver(client.person());
        notifyObserver(client.person(), Message.ENTERED);
        clients.add(client);
    }

    @Override
    public String toString() {
        return "SalesEvent";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof SalesEvent that)) return false;
        return Objects.equals(getPrices(), that.getPrices());
    }

    @Override
    public int hashCode() {
        return Objects.hash(31*71*131);
    }
}
